import type {
  AxiosInstance,
  AxiosRequestConfig,
  InternalAxiosRequestConfig,
  AxiosError,
  AxiosResponse
} from "axios";
import axios from "axios";
import event from "./eventEmitter";
import type { ResultData } from "./interface";

class Request {
  private service: AxiosInstance;

  constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config);
    
    /** 请求拦截器 */
    this.service.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        // 在请求发送时处理一些内容
        // 比如在请求头中添加 token
        const token = localStorage.getItem("token");
        if (token) { 
          config.headers.Authorization = "Bearer " + token;
        }
        return config;
      },
      (error: AxiosError) => {
        return Promise.reject(error);
      }
    );
    /** 响应拦截器 */
    this.service.interceptors.response.use(
      (response: AxiosResponse) => { 
        const { data } = response;
        
        if (data.code === RequestEnums.LOGINTIMEOUT) { 
          event.emit("API:SESSION_EXPIRED");
          return Promise.reject(data);
        }
        if (data.code !==  RequestEnums.SUCCESS) { 
          event.emit("API:INVALID");
          return Promise.reject(data);
        }
        return data;
      },
      (error: AxiosError) => { 
        event.emit("API:NETWORK_ERROR");
        return Promise.reject(error)
      }
    );
  }

  get<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.get(url, { params });
  }
  post<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.post(url, params);
  }
  put<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.put(url, params);
  }
  delete<T>(url: string, params?: object): Promise<ResultData<T>> { 
    return this.service.delete(url, { params });
  }
}

enum RequestEnums {
  TIMEOUT = 10000, // 请求超时
  FAIL = 500, // 服务器异常
  INVALID = 400, // 参数错误
  LOGINTIMEOUT = 401, // 登录超时
  SUCCESS = 200, // 请求成功
}

const config: AxiosRequestConfig = {
  baseURL: import.meta.env.VITE_APP_API_URL as string,
  timeout: RequestEnums.TIMEOUT as number,
  withCredentials: true,
};

const request = new Request(config);

export default request;
